//
//  LbxCamera.m
//  TYJiangSu
//
//  Created by liboxiang on 2019/3/27.
//  Copyright © 2019 liboxiang. All rights reserved.
//

#import "LbxCamera.h"
#import <AVFoundation/AVFoundation.h>

typedef NS_ENUM(NSInteger,AVCaptureDeviceCustomType) {
    AVCaptureDeviceCustomTypeBackCamera         = 0,
    AVCaptureDeviceCustomTypeFrontCamera        = 1,
};

@interface LbxCamera ()<AVCapturePhotoCaptureDelegate>

@property (strong, nonatomic) AVCaptureSession *captureSession;
@property (assign, nonatomic) AVCaptureDevicePosition currentPosition;
@property (strong, nonatomic) AVCaptureStillImageOutput *stillImageOutput;

@property (strong, nonatomic) AVCaptureOutput *photoOutput;
@property (strong, nonatomic) NSObject *outputSettings;

@property (copy, nonatomic) LbxCameraCompletion completionBlock;

@end

@implementation LbxCamera

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
}

- (void)setupUI {
    CGFloat takeButtonHeightAndWidth = 80;
    CGFloat buttomOffSet = 40;
    UIButton *takePhotoButton = [[UIButton alloc] initWithFrame:CGRectMake((CGRectGetWidth(self.view.bounds) - takeButtonHeightAndWidth) / 2, CGRectGetHeight(self.view.bounds) - takeButtonHeightAndWidth - buttomOffSet, takeButtonHeightAndWidth, takeButtonHeightAndWidth)];
    takePhotoButton.backgroundColor = [UIColor clearColor];
    [takePhotoButton setBackgroundImage:[UIImage imageNamed:@"lbx_take_photo_icon"] forState:UIControlStateNormal];
    [self.view addSubview:takePhotoButton];
    [takePhotoButton addTarget:self action:@selector(takePhotoButtonOnClick) forControlEvents:UIControlEventTouchUpInside];
    
    CGFloat closeButtonHeight = 20;
    CGFloat closeButtonWidth = 35;
    UIButton *closeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(30, CGRectGetHeight(self.view.bounds) - (takeButtonHeightAndWidth + closeButtonHeight) / 2 - buttomOffSet, closeButtonWidth, closeButtonHeight)];
    [closeCameraButton setBackgroundImage:[UIImage imageNamed:@"lbx_close_camera_icon"] forState:UIControlStateNormal];
    [self.view addSubview:closeCameraButton];
    [closeCameraButton addTarget:self action:@selector(closeCamera) forControlEvents:UIControlEventTouchUpInside];
    
    CGFloat switchButtonHeightAndWidth = 35;
    UIButton *switchCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.bounds) - switchButtonHeightAndWidth - 30, CGRectGetHeight(self.view.bounds) - (takeButtonHeightAndWidth + switchButtonHeightAndWidth) / 2 - buttomOffSet, switchButtonHeightAndWidth, switchButtonHeightAndWidth)];
    [switchCameraButton setBackgroundImage:[UIImage imageNamed:@"lbx_switch_camera_icon"] forState:UIControlStateNormal];
    [self.view addSubview:switchCameraButton];
    [switchCameraButton addTarget:self action:@selector(switchCamera) forControlEvents:UIControlEventTouchUpInside];
}
     
- (void)closeCamera {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)switchCamera {
    if (![LbxCamera checkCameraAuthorization]) {
        [LbxCamera showCannotUseCameraTips];
        return;
    }
    [_captureSession beginConfiguration];
    NSArray *inputs = [NSArray arrayWithArray:_captureSession.inputs];
    for (AVCaptureInput *input in inputs) {
        [_captureSession removeInput:input];
    }
    
    if (_currentPosition == AVCaptureDevicePositionBack) {
        //当前为后置摄像头
        _currentPosition = AVCaptureDevicePositionFront;
        AVCaptureDevice *device = [LbxCamera getDeviceWithType:AVCaptureDeviceCustomTypeFrontCamera];
        AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:nil];
        if ([_captureSession canAddInput:cameraDeviceInput]) {
            [_captureSession addInput:cameraDeviceInput];
        }
    }
    else {
        //当前为前置摄像头
        _currentPosition = AVCaptureDevicePositionBack;
        AVCaptureDevice *device = [LbxCamera getDeviceWithType:AVCaptureDeviceCustomTypeBackCamera];
        AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:nil];
        if ([_captureSession canAddInput:cameraDeviceInput]) {
            [_captureSession addInput:cameraDeviceInput];
        }
    }
    [_captureSession commitConfiguration];
}

- (void)takePhotoButtonOnClick {
    if (![LbxCamera checkCameraAuthorization]) {
        [LbxCamera showCannotUseCameraTips];
        return;
    }
    if (_stillImageOutput) {
        AVCaptureConnection *videoConnection = nil;
        for (AVCaptureConnection *connection in _stillImageOutput.connections) {
            for (AVCaptureInputPort *port in [connection inputPorts]) {
                if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
                    videoConnection = connection;
                    break;
                }
            }
        }
        if (videoConnection) {
            __weak typeof(self) weakSelf = self;
            [_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:
             ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
                 NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
                 UIImage *image = [[UIImage alloc] initWithData:imageData];
                 if(weakSelf.completionBlock) {
                     weakSelf.completionBlock(image);
                 }
             }];

        }
    }
    else if(_photoOutput) {
        if (@available(iOS 10.0, *)) {
            AVCapturePhotoSettings *setting = [AVCapturePhotoSettings photoSettingsFromPhotoSettings:(AVCapturePhotoSettings *)_outputSettings];
            //不能直接用_outputSettings，否则如果重复拍照会出现[AVCapturePhotoOutput capturePhotoWithSettings:delegate:] Settings may not be re-used'报错
            [(AVCapturePhotoOutput *)_photoOutput capturePhotoWithSettings:setting delegate:self];
        } else {
            // Fallback on earlier versions
        }
    }
}

- (void)openCamera {
    //摄像头
    _currentPosition = AVCaptureDevicePositionBack;
    AVCaptureDevice *backCameraDevice = [LbxCamera getDeviceWithType:AVCaptureDeviceCustomTypeBackCamera];
    
    _captureSession = [AVCaptureSession new];
//    _captureSession.sessionPreset = AVCaptureSessionPresetMedium;//定义照片质量
    AVCaptureDeviceInput *cameraDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:backCameraDevice error:nil];
    if ([_captureSession canAddInput:cameraDeviceInput]) {
        [_captureSession addInput:cameraDeviceInput];
    }
    else {
        [LbxCamera showCannotUseCameraTips];
        return;
    }
    if (@available(iOS 10.0, *)) {
        AVCapturePhotoOutput *photoOutput = [[AVCapturePhotoOutput alloc] init];
        NSDictionary *setDic = @{AVVideoCodecKey:AVVideoCodecJPEG};
        _outputSettings = [AVCapturePhotoSettings photoSettingsWithFormat:setDic];
        [photoOutput setPhotoSettingsForSceneMonitoring:(AVCapturePhotoSettings *)_outputSettings];
        if ([_captureSession canAddOutput:photoOutput]) {
            [_captureSession addOutput:photoOutput];
            _photoOutput = photoOutput;
        }
        //设置输出图片方向
        AVCaptureConnection *connection = [photoOutput connectionWithMediaType:AVMediaTypeVideo];
        if ([connection isVideoOrientationSupported])
        {
            [connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
        }
        //自动对焦，配置device的时候要先lock
        if ([connection isVideoOrientationSupported])
        {
            if ([backCameraDevice lockForConfiguration:nil]) {
                [backCameraDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
                [backCameraDevice unlockForConfiguration];
            }
        }
    } else {
        // Fallback on earlier versions
        _stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
        if ([_captureSession canAddOutput:_stillImageOutput]) {
            [_captureSession addOutput:_stillImageOutput];
        }
        //设置输出图片方向
        AVCaptureConnection *connection = [_stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
        if ([connection isVideoOrientationSupported])
        {
            [connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
        }
        //自动对焦，配置device的时候要先lock
        if ([connection isVideoOrientationSupported])
        {
            if ([backCameraDevice lockForConfiguration:nil]) {
                [backCameraDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
                [backCameraDevice unlockForConfiguration];
            }
        }
    }
    
    AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
    [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
    [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    previewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
    CALayer *rootLayer = self.view.layer;
    [rootLayer setMasksToBounds:YES];
    [previewLayer setFrame:[rootLayer bounds]];
    [rootLayer insertSublayer:previewLayer atIndex:0];
    
    [_captureSession startRunning];
    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:self animated:YES completion:nil];
}

+ (void)openCamera:(LbxCameraCompletion)completionBlock {
    LbxCamera *controller = [LbxCamera new];
    //判断是否可以打开照相机
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        controller.completionBlock = completionBlock;
        [controller openCamera];
       
    } else {
        [LbxCamera showCannotUseCameraTips];
    }
}

+ (void)showCannotUseCameraTips {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"你的设备不支持拍照。" preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *sureAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    [alertController addAction:sureAction];
    [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:^{
        
    }];
}
//检查相机权限
+ (BOOL)checkCameraAuthorization {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    switch (authStatus) {
        case AVAuthorizationStatusNotDetermined:
            //没有询问是否开启相机
//            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
//                NSLog(@"%@",granted ? @"相机准许":@"相机不准许");
//            }];
            break;
        case AVAuthorizationStatusRestricted:
            //未授权，家长限制
            
            break;
        case AVAuthorizationStatusDenied:
            //未授权
            
            break;
        case AVAuthorizationStatusAuthorized:
            //玩家授权
            return YES;
            break;
        default:
            break;
    }
    return NO;
}

//获取对应类型的设备device
+ (AVCaptureDevice *)getDeviceWithType:(AVCaptureDeviceCustomType)type {
    NSArray * devices;
    if (@available(iOS 10.0, *)) {
        AVCaptureDevicePosition position;
        switch (type) {
            case AVCaptureDeviceCustomTypeBackCamera:
                position = AVCaptureDevicePositionBack;
                break;
            case AVCaptureDeviceCustomTypeFrontCamera:
                position = AVCaptureDevicePositionFront;
                break;
        }
        devices = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:position].devices;
    } else {
        // Fallback on earlier versions
        devices = [AVCaptureDevice devices];
    }
    
    AVCaptureDevice *resultDevice = nil;
    for (AVCaptureDevice *device in devices) {
        if (type == AVCaptureDeviceCustomTypeBackCamera || type == AVCaptureDeviceCustomTypeFrontCamera) {
            //摄像头
            if ([device hasMediaType:AVMediaTypeVideo]) {
                
                if ([device position] == AVCaptureDevicePositionBack && type == AVCaptureDeviceCustomTypeBackCamera) {
                    resultDevice = device;
                    break;
                }
                else if ([device position] == AVCaptureDevicePositionFront && type == AVCaptureDeviceCustomTypeFrontCamera){
                    resultDevice = device;
                    break;
                }
            }
        }
    }
    
    return resultDevice;
}

#pragma mark - AVCapturePhotoCaptureDelegate
- (void)captureOutput:(AVCapturePhotoOutput *)captureOutput didFinishProcessingPhotoSampleBuffer:(nullable CMSampleBufferRef)photoSampleBuffer previewPhotoSampleBuffer:(nullable CMSampleBufferRef)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(nullable AVCaptureBracketedStillImageSettings *)bracketSettings error:(nullable NSError *)error  API_AVAILABLE(ios(10.0)){
    
    NSData *data = [AVCapturePhotoOutput JPEGPhotoDataRepresentationForJPEGSampleBuffer:photoSampleBuffer previewPhotoSampleBuffer:previewPhotoSampleBuffer];
    UIImage *image = [UIImage imageWithData:data];
    if(_completionBlock) {
        _completionBlock(image);
    }
}

@end
